#pragma once
#include "task.hpp"

namespace My_Process_Pool
{
    // typedef std::function<int()> work_t;
    // using work_t = std::function<void()>;

    // 管道和子进程管理
    // 管道
    struct Channel
    {
        int _fd;
        pid_t _id;
        std::string _name;
        // 构造函数
        Channel() = default;
        void _setname()
        {
            _name = "Channel fd: " + std::to_string(_fd) + " id: " + std::to_string(_id);
        }
        Channel(int fd, pid_t id)
            : _fd(fd), _id(id)
        {
            _setname();
            // std::cout << _name << std::endl;
        }
        // 发送任务
        ssize_t _send(int tasknum)
        {
            ssize_t record = ::write(_fd, &tasknum, sizeof(tasknum));
            std::cout << "send: write " << _id << " " << _fd << " " << tasknum << std::endl;
            return record;
        }
        // 关闭管道
        int _close()
        {
            int record = ::close(_fd);
            return record;
        }
        // 拷贝构造
        Channel(const Channel &cpy) = delete;
        // 赋值重载
        Channel operator=(const Channel &cpy) = delete;
        // 析构
        ~Channel() = default;
    };

    // 管道和子进程集合
    // 进程池
    // template <class T>
    class ProcessPool
    {
    public:
        // 构造函数
        ProcessPool() = default;
        // 拷贝构造
        ProcessPool(const ProcessPool &cpy) = delete;
        // 赋值重载
        ProcessPool operator=(const ProcessPool &cpy) = delete;
        // 析构
        ~ProcessPool()
        {
            std::cout << "析构" << std::endl;
            clear();
        }

        // push_back
        // void push_back(T *t)
        void push_back(Channel *t)
        {
            _channels.emplace_back(t);
            //++_size;
        }

        // pop_back
        void pop_back()
        {
            _channels.pop_back();
            //--_size;
        }
        // erase ->index 下标
        void erase(int index)
        {
            auto it = _channels.begin();
            it += index;
            _channels.erase(it);
            //--_size;
        }

        // new
        bool new_back(Channel *t)
        {
            // 创建管道
            int newfd[2] = {0};
            int piperet = pipe(newfd);
            if (piperet != 0)
            {
                // 管道建立失败
                std::cout << "管道建立失败" << piperet << std::endl;
                return false;
            }
            // 创建子进程
            pid_t childid = fork();
            if (childid == 0)
            {
                // 回收父进程资源
                clear();
                // 子进程建立管道
                ::close(newfd[1]);
                // 子进程任务
                std::cout << "子进程任务run " << getpid() << std::endl;
                // dup2(newfd[0], 0);
                _work(newfd[0]);
                // 子进程结束，回收资源
                std::cout << "子进程任务end " << getpid() << std::endl;
                ::close(newfd[0]);
                exit(0);
            }
            else if (childid > 0)
            {
                // 父进程建立管道
                ::close(newfd[0]);
                // Channel newchannel(newfd[1], childid);
                t->_fd = newfd[1];
                t->_id = childid;
                t->_setname();
                // std::cout << t->_name << std::endl;
                _channels.emplace_back(t);
                //++_size;
                return true;
            }
            else
            {
                // 子进程创建失败
                std::cout << "子进程创建失败" << std::endl;
                return false;
            }
        }

        // send
        void send(int index, int workindex)
        {
            _channels[index]->_send(workindex);
        }

        // size
        int size()
        {
            return _channels.size();
        }

        // clear
        void clear()
        {
            if (_channels.empty())
            {
                return;
            }
            for (int i = _channels.size() - 1; i < 0; i--)
            {
                _channels[i]->_close();
                _channels.pop_back();
            }
            //_size = 0;
        }

        // work
        void _work(int fd)
        {
            while (1)
            {
                int workid = _mytask._wait(fd);
                int t = 0;
                switch (workid)
                {
                case 0: // login_work
                    t = 1;
                    break;
                case 1: // logout_work
                    t = 1;
                    break;
                case 2: // send_work
                    t = 1;
                    break;
                case 3: // receive_work
                    t = 1;
                    break;
                case 4: // save_work
                    t = 1;
                    break;
                case 5: // find_work
                    t = 1;
                    break;
                default:
                    return;
                }
                _mytask._workrun(workid, t);
            }
        }

        void print()
        {
            for (auto it : _channels)
            {
                std::cout << it->_name << std::endl;
            }
        }

    private:
        // std::vector<T *> _channels;
        std::vector<Channel *> _channels;
        // int _size = 0;
        Task_Pool _mytask;
    };

}
